package org.third.integration.vault.imp;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.third.common.SS_CONSTANT;
import org.third.common.utils.EnvUtils;
import org.third.common.utils.HttpClientUtils;
import org.third.integration.etcd.KubeEtcdClient;
import org.third.integration.vault.HttpVaultBinClient;
import org.third.integration.vault.bean.SecretInstanceInfo;
import org.third.integration.vault.bean.VaultInstanceInfo;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

@Service
public class HttpVaultBinClientImp implements HttpVaultBinClient {

	private CloseableHttpClient httpclient = HttpClientUtils.getCertificateIngnoredAndWithClientCertificateHttpClient(
			EnvUtils.getEtcdclientcertificatefile(), EnvUtils.getEtcdclientcertificatepwd());

	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private KubeEtcdClient kubeEtcdClient;

	private String getVaultToken() {

		String vaultToken = kubeEtcdClient.get(SS_CONSTANT.VAULT_RT_TOKEN);
		return vaultToken;
	}

	protected HttpGet prepareHttpGet(String requestPath, Map<String, String> headers)
			throws JsonGenerationException, JsonMappingException, IOException {
		HttpGet httpGet = new HttpGet(requestPath);

		for (Entry<String, String> entry : headers.entrySet()) {
			System.out.println("entry.getKey():" + entry.getKey());
			System.out.println("entry.getValue():" + entry.getValue());
			httpGet.addHeader(entry.getKey(), entry.getValue());
		}
		return httpGet;

	}

	@Override
	public VaultInstanceInfo getVaultList(String type, String url) {

		VaultInstanceInfo vaultInstanceInfo = new VaultInstanceInfo(type, url, "");

		CloseableHttpResponse response = null;
		try {
			String fullUrl = EnvUtils.getVaultendpoints() + "/" + url;
			;
			logger.info("fullUrl:" + fullUrl);
			// HttpGet httpGet = new HttpGet(fullUrl);
			String vaultToken = getVaultToken();
			Map<String, String> headers = new HashMap<String, String>();
			headers.put("X-Vault-Token", vaultToken);
			HttpGet httpGet = prepareHttpGet(fullUrl, headers);

			response = httpclient.execute(httpGet);
			System.out.println("response:" + response.getStatusLine());
			if (response.getStatusLine().getStatusCode() != 200 && response.getStatusLine().getStatusCode() != 201
					&& response.getStatusLine().getStatusCode() != 204) {
				HttpEntity entity = response.getEntity();
				String content = IOUtils.toString(entity.getContent(), "UTF-8");
				String errMsg = String.format("%s%s%s", response.getStatusLine().toString(), System.lineSeparator(),
						content);
				throw new RuntimeException(errMsg);
			} else {
				HttpEntity entity = response.getEntity();
				String content = IOUtils.toString(entity.getContent(), "UTF-8");
				System.out.println("content:" + content);
				vaultInstanceInfo.setStatusCode(response.getStatusLine().getStatusCode());
				vaultInstanceInfo.setResponseBody(content);
			}
		} catch (Exception e) {
			throw new RuntimeException("=====error", e);
		} finally {
			if (response != null) {
				try {
					response.close();
				} catch (IOException e) {
					logger.warn("something wrong when closing response.", e);
				}
			}
		}

		return vaultInstanceInfo;
	}

	protected HttpDelete prepareHttpDelete(String requestPath, Map<String, String> headers)
			throws JsonGenerationException, JsonMappingException, IOException {
		HttpDelete httpDelete = new HttpDelete(requestPath);

		for (Entry<String, String> entry : headers.entrySet()) {
			System.out.println("entry.getKey():" + entry.getKey());
			System.out.println("entry.getValue():" + entry.getValue());
			httpDelete.addHeader(entry.getKey(), entry.getValue());
		}
		return httpDelete;

	}

	@Override
	public VaultInstanceInfo delete(String type, String url) {

		VaultInstanceInfo vaultInstanceInfo = new VaultInstanceInfo(type, url, "");

		CloseableHttpResponse response = null;
		try {
			String fullUrl = EnvUtils.getVaultendpoints() + "/" + url;
			;
			logger.info("fullUrl:" + fullUrl);
			// HttpGet httpGet = new HttpGet(fullUrl);
			String vaultToken = getVaultToken();
			Map<String, String> headers = new HashMap<String, String>();
			headers.put("X-Vault-Token", vaultToken);
			HttpDelete httpDelete = prepareHttpDelete(fullUrl, headers);

			response = httpclient.execute(httpDelete);
			System.out.println("response:" + response.getStatusLine());
			if (response.getStatusLine().getStatusCode() == 204 || response.getStatusLine().getStatusCode() == 200
					|| response.getStatusLine().getStatusCode() == 201) {
				vaultInstanceInfo.setStatusCode(response.getStatusLine().getStatusCode());
			} else {
				throw new RuntimeException(response.getStatusLine().getStatusCode() + "");
			}
		} catch (Exception e) {
			throw new RuntimeException("=====error", e);
		} finally {
			if (response != null) {
				try {
					response.close();
				} catch (IOException e) {
					logger.warn("something wrong when closing response.", e);
				}
			}
		}

		return vaultInstanceInfo;
	}

	@Override
	public SecretInstanceInfo deleteSecret(String type, String url) {
		SecretInstanceInfo secretInstanceInfo = new SecretInstanceInfo(type, url, "");
		CloseableHttpResponse response = null;

		try {
			String fullUrl = EnvUtils.getVaultendpoints() + "/" + url;
			logger.info("fullUrl:" + fullUrl);

			String valutToken = getVaultToken();
			Map<String, String> headers = new HashMap<String, String>();
			headers.put("X-Vault-Token", valutToken);
			HttpDelete httpDelete = prepareHttpDelete(fullUrl, headers);

			response = httpclient.execute(httpDelete);
			System.out.println("response:" + response.getStatusLine());
			if (response.getStatusLine().getStatusCode() == 204 || response.getStatusLine().getStatusCode() == 200
					|| response.getStatusLine().getStatusCode() == 201) {
				secretInstanceInfo.setStatusCode(response.getStatusLine().getStatusCode());
			} else {
				throw new RuntimeException(response.getStatusLine().getStatusCode() + "");
			}
		} catch (Exception e) {
			throw new RuntimeException("=====error", e);
		} finally {
			if (response != null) {
				try {
					response.close();
				} catch (IOException e) {
					logger.warn("something wrong when closing response.", e);
				}
			}
		}
		return secretInstanceInfo;

	}

}
